home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / dec / qdss / libtl / tldma.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-26  |  23.0 KB  |  703 lines

  1. /***********************************************************
  2. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. #ifndef lint
  26. static char *sccsid = "@(#)tldma.c    1.4    8/11/87";
  27. static char rcsid[] = "$XConsortium: tldma.c,v 1.3 89/11/26 18:07:49 keith Exp $";
  28. #endif lint
  29.  
  30. /************************************************************************
  31.  *                                    *
  32.  *            Copyright (c) 1985, 1986 by            *
  33.  *        Digital Equipment Corporation, Maynard, MA        *
  34.  *            All rights reserved.                *
  35.  *                                    *
  36.  *   This software is furnished under a license and may be used and    *
  37.  *   copied  only  in accordance with the terms of such license and    *
  38.  *   with the  inclusion  of  the  above  copyright  notice.   This    *
  39.  *   software  or  any  other copies thereof may not be provided or    *
  40.  *   otherwise made available to any other person.  No title to and    *
  41.  *   ownership of the software is hereby transferred.            *
  42.  *                                    *
  43.  *   The information in this software is subject to change  without    *
  44.  *   notice  and should not be construed as a commitment by Digital    *
  45.  *   Equipment Corporation.                        *
  46.  *                                    *
  47.  *   Digital assumes no responsibility for the use  or  reliability    *
  48.  *   of its software on equipment which is not supplied by Digital.    *
  49.  *                                    *
  50.  ************************************************************************/
  51.  
  52. #include <errno.h>
  53. #include <sys/time.h>
  54. #include        "Ultrix2.0inc.h"
  55. #include        "tl.h"
  56.  
  57. /* These used by uVaxII */
  58. #include    <vaxuba/qdioctl.h>
  59. #include    <vaxuba/qduser.h>
  60. #include        <vaxuba/qdreg.h>
  61. /* end - uVaxII    */
  62.  
  63. /* These used by Vaxstar */
  64. #include "tlsg.h"
  65. /* end - Vaxstar  */
  66.  
  67. extern int errno;
  68.  
  69. #ifdef DEBUG
  70. int DebugDma = 0; /* used in tl.h */
  71. long NextSaveDmaSlot = 0;
  72. long SaveDmaSlots[16];
  73. SaveDmaPC()
  74. {
  75.     register callersPC; /* r11 if PCC */
  76. #ifdef __GNUC__
  77.     asm(" movl 16(fp),%0" : "=r" (callersPC));
  78. #else
  79.     asm(" movl 16(fp),r11");
  80. #endif
  81.     SaveDmaSlots[NextSaveDmaSlot&15] = callersPC;
  82.     NextSaveDmaSlot++;
  83. }
  84. #endif
  85.  
  86. /* These used by Vaxstar */
  87. extern VOLATILE short  * sg_int_flag; /* Ugly hack? is set in the driver */
  88. extern VOLATILE short  * change_section; /* so is change_section          */
  89. short    sg_fifo_func = 0;
  90. /* end - Vaxstar  */
  91.  
  92. /* These used by uVaxII */
  93. struct DMAreq *DMArequest; /* pointer to per-packet header of current packet */
  94. u_short *DMAbuf;       /* either a pointer to the beginning of the current
  95. /* end - uVaxII    */
  96.  
  97. /* These used by Vaxstar */
  98. struct FIFOreq *FIFOrequest;
  99. u_short *SG_Fifo;   
  100. u_short sg_fifo_type;
  101. VOLATILE struct  fcc *fcc_cbcsr;
  102. /* end - Vaxstar */
  103.  
  104. u_short *dma_word;    /* tail of packet under construction */
  105. u_short *req_buf_max;   /* pointer to word following    */
  106. u_short *dma_max;       /* expected end of dma list. touched only in tl.h */
  107.  
  108. int    last_DMAtype;
  109. int     req_buf_size;      /* size (in words) of a single packet  */
  110. int     total_buf_size;    /* sum of sizes (in bytes) of packets */
  111.  
  112. VOLATILE unsigned short *AdderPtr;    /* this is initialized in tlInit */
  113.  
  114. #define        NUM_DMAreq      3
  115.  
  116. Enable_dma()
  117. {
  118.     register struct dga *dga = Dga;
  119.  
  120.     int    i;        /* loop counter */
  121.  
  122.     /*
  123.      * halt pending ops
  124.      */
  125.  
  126.     dga->csr &= HALT_DMA_OPS;
  127.  
  128.     /********************************************************/
  129.     /* see if the DMA iobuf needs to be mapped to the user    */
  130.     /********************************************************/
  131.  
  132.     if (DMAheader == 0) {
  133.         if (ioctl(fd_qdss, QD_MAPIOBUF, &DMAheader) == -1) {
  134.             printf("ioctl() error. errno = %d\n", errno);
  135.             exit (1);
  136.         }
  137.     }
  138.  
  139.     /****************************************************************/
  140.     /* initialize total number of request buffers in the request    */
  141.     /* queue                            */
  142.     /****************************************************************/
  143.  
  144.     DMAheader->size = NUM_DMAreq;
  145.     DMAheader->used = DMAheader->oldest = DMAheader->newest = 0;
  146.  
  147.     dga->csr |= DMA_IE;    /* flush any spurious interrupts */
  148.     
  149.     /****************************************************************/
  150.     /* initialize sum of sizes of request buffers, expressed in     */
  151.     /* number of bytes                        */
  152.     /****************************************************************/
  153.  
  154.     total_buf_size =     DMAheader->shared_size 
  155.                - sizeof (struct DMAreq_header) 
  156.                - (NUM_DMAreq * sizeof (struct DMAreq)) ;
  157.  
  158.  
  159.  
  160.     /****************************************************************/
  161.     /* initialize size of individual request buffers in words     */
  162.     /****************************************************************/
  163.  
  164.     req_buf_size = (total_buf_size / NUM_DMAreq) / sizeof(short);
  165.  
  166.     /****************************************************************/
  167.     /* initialze the address to the start of the dma buffers in     */
  168.     /* each request entry header and the pointers into those     */
  169.     /* buffers.  then make the DMAbuf pointer nil to signal that     */
  170.     /* there is no display currently being built.            */
  171.     /****************************************************************/
  172.  
  173.     DMAbuf =  (u_short *) &DMAheader->DMAreq[NUM_DMAreq];
  174.     for (i=0; i<NUM_DMAreq; i++) {
  175.         DMAheader->DMAreq[i].bufp = (char *) DMAbuf;
  176.         DMAbuf += req_buf_size;
  177.     }
  178.     DMAbuf = 0;
  179.     /*
  180.      * to prevent first Need_dma from flushing
  181.      */
  182.     dma_word = req_buf_max = (u_short *) req_buf_size;
  183.  
  184.     last_DMAtype = (-1);
  185.  
  186. }
  187.  
  188. /*
  189.  * This routine will enable the FIFO capability of the VAXstar hardware. This routine
  190.  * will set a flag which indicates that we want to use the FIFO for future 
  191.  * operations.
  192.  */
  193.  
  194. Enable_fifo()
  195. {
  196.     register VOLATILE struct fcc *sgfcc = fcc_cbcsr;
  197.  
  198.     int    i;        /* loop counter */
  199.  
  200.     /********************************/
  201.     /* first set the FIFO flag    */
  202.     /********************************/
  203.  
  204.     FIFOflag = TRUE;
  205.  
  206.         /********************************************************/
  207.         /* see if the FIFO iobuf needs to be mapped to the user  */
  208.         /********************************************************/
  209.  
  210.         if (FIFOheader == 0)
  211.                 ioctl(fd_qdss, QD_MAPIOBUF, &FIFOheader, 0);
  212.         *(unsigned long *) &sgfcc->cbcsr = (unsigned long) 0;
  213.         *(unsigned long *) &sgfcc->put = (unsigned long ) 0;
  214.         sgfcc->thresh = 0x0000;
  215.         *(unsigned long *)&sgfcc->cbcsr |= 
  216.         (unsigned long)(((sgfcc->icsr|ENTHRSH)<<16)|DL_ENB);
  217.  
  218.         /****************************************************************/
  219.         /* initialize total number of request buffers in the request    */
  220.         /* queue                                                        */
  221.         /****************************************************************/
  222.  
  223.         FIFOheader->size = NUM_DMAreq;
  224.         FIFOheader->used = FIFOheader->oldest = FIFOheader->newest = 0;
  225.  
  226.  
  227.         /****************************************************************/
  228.         /* initialize sum of sizes of request buffers, expressed in     */
  229.         /* number of bytes                                              */
  230.         /****************************************************************/
  231.  
  232.         total_buf_size =     FIFOheader->shared_size
  233.                            - sizeof (struct FIFOreq_header)
  234.                            - (NUM_DMAreq * sizeof (struct FIFOreq)) ;
  235.  
  236.  
  237.  
  238.         /****************************************************************/
  239.         /* initialize size of individual request buffers in words and   */
  240.         /* some FIFO related variables.                                 */
  241.         /****************************************************************/
  242.  
  243.     req_buf_size = (total_buf_size / NUM_DMAreq) / sizeof(short);
  244.     *sg_next_fifo = 0;  /* This points to next available word in FIFO */
  245.     
  246.  
  247.         /****************************************************************/
  248.         /* initialze the address to the start of the dma buffers in     */
  249.         /* each request entry header and the pointers into those        */
  250.         /* buffers.  then make the DMAbuf pointer nil to signal that    */
  251.         /* there is no display currently being built.                   */
  252.         /****************************************************************/
  253.  
  254.         DMAbuf = 0;
  255.         /*
  256.          * to prevent first Need_dma from flushing
  257.          */
  258.         dma_word = req_buf_max = (u_short *) req_buf_size;
  259.  
  260.         last_DMAtype = (-1);
  261.  
  262. }
  263.  
  264.  
  265.  
  266. Flush_dma (wait_flag)
  267.     int    wait_flag;    /* wait for adder address completion before returning */
  268. {
  269.     register u_short *DMAbuf_ptr;
  270.  
  271.     /****************************************************************/
  272.     /* *dga MUST be a register variable to ensure that the         */
  273.     /* optimizer generates instructions that can be performed on     */
  274.     /* device registers                        */
  275.     /****************************************************************/
  276.  
  277.     register struct dga *dga = Dga;
  278.     register VOLATILE struct  DMAreq_header    *DMAhdr = DMAheader;
  279.     register u_short *p;
  280.     register struct DMAreq    *reqst = (struct DMAreq    *) DMArequest;
  281.     int cookie;
  282.  
  283.     struct timeval timeout;
  284.     int selmask;
  285.  
  286.     /*
  287.      * timeout needs to be small, to accomodate race condition in loop
  288.      */
  289.     timeout.tv_sec = (long) 0;
  290.     timeout.tv_usec = (long) 17000;    /* 1/60 sec. */
  291.  
  292. #ifdef undef
  293.     /* determine if there is really something to send */
  294.     if ( dma_word - DMAbuf == 0 && wait_flag == TRUE)
  295.     return;
  296. #endif
  297.  
  298.     if ((wait_flag == TRUE) || (DMAbuf != 0)) {
  299.         /********************************************************/
  300.         /* if the wait_flag is true, then check the DMAbuf     */
  301.         /* pointer.  if the DMAbuf pointer is nil, then queue     */
  302.         /* a no-op DISPLIST request that will wait for the FIFO */
  303.         /* to be empty before it signals DMAdone.  if the     */
  304.         /* DMAbuf pointer is not nil, then change the done    */
  305.         /* condition of the existing DMA request to be         */
  306.         /* FIFO_EMPTY.  this will ensure that dma activity is     */
  307.         /* completely finished                    */
  308.         /********************************************************/
  309.  
  310.         if (wait_flag == TRUE)
  311.             if (DMAbuf == 0) {
  312.                 Get_dma ( FIFO_EMPTY );
  313.                 reqst = DMArequest;
  314.                 Need_dma ( 3 );
  315.                 *p++ = (PNT(REQUEST_ENABLE));
  316.                 *p++ = (ADDRESS);
  317.                 *p++ = (PNT(ADDRESS_COUNTER));
  318.                 Confirm_dma();
  319.             } else {
  320.                 reqst->DMAdone |= FIFO_EMPTY;
  321.                 reqst->DMAdone &= ~COUNT_ZERO;
  322.             }
  323.  
  324. #ifdef undef
  325.         if (reqst->DMAtype == DISPLIST)
  326. #endif
  327.             reqst->length = (dma_word - DMAbuf) * sizeof(short);
  328.  
  329.         /********************************************************/
  330.         /* update pointers and counters in the DMA request     */
  331.         /* queue header                        */
  332.         /********************************************************/
  333.     
  334.         DMA_PUTEND (DMAhdr);
  335.     
  336.     
  337.         /********************************************************/
  338.         /* test to see if there is a DMA in progress, or if     */
  339.         /* this is a "cold start"                */
  340.         /********************************************************/
  341.     
  342.         if (! DMA_ISACTIVE (DMAhdr) && ! DMA_ISEMPTY (DMAhdr))
  343.             {
  344.             /************************************************/
  345.             /* determine if transfers to/from ADDER need to    */
  346.             /* temporarily inhibited.  this is a MUST if     */
  347.             /* we are switching from BTOP to DISPLIST mode.    */
  348.             /* also, if we are changing modes than we need    */
  349.             /* shut down DMA operations.            */
  350.             /************************************************/
  351.  
  352.             if ( reqst->DMAtype != last_DMAtype ) {
  353.                 AdderPtr[REQUEST_ENABLE] = 0;
  354.                 Dga->csr &= ~DMA_IE;
  355.                 Dga->csr &= HALT_DMA_OPS;
  356.             }
  357.  
  358.             /**********************/
  359.             /* mark DMA as active */
  360.             /**********************/
  361.  
  362.             DMA_SETACTIVE (DMAhdr);
  363.  
  364.             /************************************************/
  365.             /* disable interrupt since setting COUNT ZERO    */
  366.             /* condition could trigger interrupt during    */
  367.             /* hardware set up                */
  368.             /************************************************/
  369.  
  370.             dga->csr &= ~DMA_IE;
  371.  
  372.  
  373.             /********************************/
  374.             /* clear any error condition    */
  375.             /********************************/
  376.  
  377.             dga->csr |= (DMA_ERR);
  378.         
  379.             /************************************************/
  380.             /* set up condition bits (10, 9, and 8) in the     */
  381.             /* csr.  also, load appropriate value into     */
  382.             /* Adder's REQUEST_ENABLE register.        */
  383.             /************************************************/
  384.  
  385.             switch (reqst->DMAtype)
  386.                 {
  387.                 case DISPLIST:
  388.                     dga->csr |= DL_ENB;
  389.                     dga->csr &= ~(BTOP_ENB | BYTE_DMA);
  390.                     AdderPtr[REQUEST_ENABLE] = RASTEROP_COMPLETE;
  391.                     break;
  392.                 case PTOB:
  393.                     if (reqst->DMAdone & BYTE_PACK)
  394.                         dga->csr |= (PTOB_ENB | BYTE_DMA);
  395.                     else {
  396.                         dga->csr |= PTOB_ENB;
  397.                         dga->csr &= ~BYTE_DMA;
  398.                     }
  399.                     AdderPtr[REQUEST_ENABLE] = TX_READY;
  400.                     break;
  401.                 case BTOP:
  402.                     if (reqst->DMAdone & BYTE_PACK) {
  403.                         dga->csr &= ~DL_ENB;
  404.                         dga->csr |= (BTOP_ENB | BYTE_DMA);
  405.                     } else {
  406.                         dga->csr |= BTOP_ENB;
  407.                         dga->csr &= ~(BYTE_DMA | DL_ENB);
  408.                     }
  409.                     AdderPtr[REQUEST_ENABLE] = RX_READY;
  410.                     break;
  411.                 }
  412.  
  413.  
  414.             /************************************************/
  415.             /* record request DMAtype for future calls to    */
  416.             /* this routine                    */
  417.             /************************************************/
  418.  
  419.             last_DMAtype = reqst->DMAtype;
  420.  
  421.             if (reqst->DMAdone & COUNT_ZERO)
  422.                 /****************************************/
  423.                 /* set the DMADONE bit when the dma     */
  424.                 /* byte counter (dga->bytcnt_lo and     */
  425.                 /* dga->bytcnt_hi) is 0            */
  426.                 /****************************************/
  427.  
  428.                 dga->csr &= ~SET_DONE_FIFO;
  429.  
  430.             else if (reqst->DMAdone & FIFO_EMPTY)
  431.                 /****************************************/
  432.                 /* set the DMADONE bit when the dma     */
  433.                 /* byte counter is zero, and when the     */
  434.                 /* FIFO is empty            */
  435.                 /****************************************/
  436.  
  437.                 dga->csr |= SET_DONE_FIFO;
  438.  
  439.             /************************************************/
  440.             /* calculate the next cookie.  it's the offset     */
  441.             /* of the buffer into the shared space plus     */
  442.             /* the value returned by the driver in         */
  443.             /* DMAheader->QBAreg                */
  444.             /************************************************/
  445.         
  446.             cookie = ((int)DMAbuf-(int)DMAhdr) + (int)DMAhdr->QBAreg;
  447.  
  448.             /********************************/
  449.             /* set up destination address    */
  450.             /********************************/
  451.             dga->adrs_lo = (unsigned short) cookie;
  452.             dga->adrs_hi = (unsigned short) (cookie >> 16);
  453.         
  454.             /****************************************/
  455.             /* set up byte length of transfer    */
  456.             /****************************************/
  457.             dga->bytcnt_lo = (unsigned short) reqst->length;
  458.             dga->bytcnt_hi = (unsigned short) 
  459.                 (reqst->length) >> 16;
  460.  
  461.             /********************************/
  462.             /* set up the interupt enable    */
  463.             /********************************/
  464.  
  465.             dga->csr |= DMA_IE;
  466.             }
  467.  
  468.         /********************************************************/
  469.         /* if the wait flag is true, then wait for the DMA    */
  470.         /* to complete.                        */
  471.         /********************************************************/
  472.         if (wait_flag == TRUE) {
  473.             while (DMA_ISACTIVE (DMAheader)) {
  474.             selmask = 1 << fd_qdss;
  475.             select( fd_qdss + 1, 0, &selmask, 0, &timeout);
  476.             }
  477.         }
  478.                 
  479.     }
  480.     /*
  481.      * wait for the last adder pixel address to be generated
  482.      */
  483.     if (wait_flag == TRUE)
  484.     while ( (AdderPtr[STATUS] & ADDRESS) != ADDRESS) /* ADDRESS_COMPLETE */
  485.         ;
  486.     DMAbuf = 0;
  487.     dma_word = req_buf_max = (u_short *) req_buf_size;
  488. }
  489.  
  490. Flush_fifo (wait_flag)
  491.     int    wait_flag;    /* wait for adder address completion before returning */
  492. {
  493.     register u_short *DMAbuf_ptr;
  494.  
  495.     /****************************************************************/
  496.     /* *dga MUST be a register variable to ensure that the         */
  497.     /* optimizer generates instructions that can be performed on     */
  498.     /* device registers                        */
  499.     /****************************************************************/
  500.  
  501.     register struct dga *dga = Dga;
  502.     register VOLATILE struct  DMAreq_header    *DMAhdr = DMAheader;
  503.     register u_short *p;
  504.     register VOLATILE struct fcc *sgfcc;
  505.     u_short  fifo_address;
  506.     register struct FIFOreq *reqst = (struct FIFOreq *) FIFOrequest;
  507.  
  508.     struct timeval timeout;
  509.     int selmask;
  510.  
  511.     /*
  512.      * timeout needs to be small, to accomodate race condition in loop
  513.      */
  514.     timeout.tv_sec = (long) 0;
  515.     timeout.tv_usec = (long) 17000;    /* 1/60 sec. */
  516.  
  517.     sgfcc = fcc_cbcsr;
  518.     if ((wait_flag == TRUE) || (DMAbuf != 0)) {
  519.         /********************************************************/
  520.         /* if the wait_flag is true, then check the DMAbuf     */
  521.         /* pointer.  if the DMAbuf pointer is nil, then queue     */
  522.         /* a no-op request that will wait for the FIFO to be     */
  523.         /* empty before it signals DMAdone.  if the DMAbuf     */
  524.         /* pointer is not nill, then change change the done     */
  525.         /* condition of the existing DMA request to be         */
  526.         /* FIFO_EMPTY.  this will ensure that dma activity is     */
  527.         /* completely finished                    */
  528.         /********************************************************/
  529.  
  530.         if (wait_flag == TRUE)
  531.             if (DMAbuf == 0) {
  532.                 while (sgfcc->fwused) ; /* ?? */
  533.                 Need_dma ( 3 );
  534.                 *p++ =  ( PNT(REQUEST_ENABLE) );
  535.                 *p++ =  ( ADDRESS );
  536.                 *p++ =  ( PNT ( ADDRESS_COUNTER ) );
  537.                 Confirm_dma();
  538.             }
  539.     
  540.         /**********************************************************/
  541.         /* adjust the pointer into the next available word in the */
  542.         /* FIFO (multiply dma_word by sizeof short (remember,     */
  543.         /* DMAbuf is a short).                    */
  544.         /********************************************************/
  545.     
  546. #ifdef undef
  547.         if (sg_fifo_type == DISPLIST)
  548. #endif
  549.             *sg_next_fifo += (dma_word - DMAbuf);
  550.     
  551.         /********************************************************/
  552.         /* test to see if there is a FIFO in progress, or if     */
  553.         /* this is a "cold start"                */
  554.         /********************************************************/
  555.     
  556.         if (*sg_int_flag == -1) {
  557.             /************************************************/
  558.             /* enable the adder for rasterop complete    */
  559.             /************************************************/
  560.             if ( sg_fifo_type != last_DMAtype )
  561.                 AdderPtr[REQUEST_ENABLE] = RASTEROP_COMPLETE;
  562.  
  563.             /****************************************/
  564.             /* set up condition bits in the csr    */
  565.             /****************************************/
  566.             fifo_address = sgfcc->cbcsr & 0x3;
  567.             switch (sg_fifo_type) {
  568.             case DISPLIST:
  569.                 if ((sg_fifo_type != last_DMAtype) &&
  570.                        (last_DMAtype != (-1))) {
  571.                 sgfcc->cbcsr &= 0xE0FC;
  572.                 sgfcc->cbcsr |= (DL_ENB | fifo_address);
  573.                 AdderPtr[REQUEST_ENABLE] = TX_READY;
  574.                 }
  575.                 if (*change_section == 1)
  576.                 break;
  577.                 sgfcc->put = *sg_next_fifo;
  578.                 break;
  579.  
  580.             case PTOB:
  581.                 if (sg_fifo_type != last_DMAtype) {
  582.                 while (sgfcc->fwused) ; /* ?? */
  583.                 sgfcc->cbcsr &= 0xE0FC;
  584.                 }
  585.                 AdderPtr[REQUEST_ENABLE] = TX_READY;
  586.                 sgfcc->icsr &= ~ENTHRSH;
  587.                 sgfcc->put = *sg_next_fifo;
  588.                 sgfcc->thresh = 0x0000;
  589.                 *(unsigned long *)&sgfcc->cbcsr =
  590.                    (unsigned long)((ENTHRSH<<16)|sg_fifo_func|fifo_address);
  591.                 sg_fifo_func = 0;
  592.                 break;
  593.  
  594.             case BTOP:
  595.                 if (sg_fifo_type != last_DMAtype) {
  596.                 while (sgfcc->fwused) ; /* ?? */
  597.                 sgfcc->cbcsr &= 0xE0FC;
  598.                 }
  599.  
  600.                 AdderPtr[REQUEST_ENABLE] = RX_READY;
  601.                    sgfcc->icsr &= ~ENTHRSH;
  602.             sgfcc->thresh = (dma_word - DMAbuf) * 2;
  603.                 *(unsigned long *)&sgfcc->cbcsr =
  604.                       (unsigned long)((ENTHRSH<<16)|sg_fifo_func|fifo_address);
  605.                 sg_fifo_func = 0;
  606.                 break;
  607.             }
  608.             last_DMAtype = sg_fifo_type;
  609.         }
  610.  
  611.         /********************************************************/
  612.         /* if the input flag is true, then wait for the FIFO    */
  613.         /* to complete.                        */
  614.         /********************************************************/
  615.         if (wait_flag == TRUE) {
  616.             while (*sg_int_flag != -1) ;
  617.             while ((sgfcc->fwused) || (*change_section == 1)) ; /* ?? */
  618.             while ( (AdderPtr[STATUS] & ADDRESS) != ADDRESS);
  619.         }
  620.     }
  621.     DMAbuf = 0;
  622.     dma_word = req_buf_max = (u_short *) req_buf_size;
  623. }
  624.  
  625.  
  626. Get_dma (condition)
  627.     short condition; /* to be put in new packet header's DMAdone field */
  628. {
  629.     struct timeval timeout;
  630.     int selmask;
  631.  
  632.     /*
  633.      * timeout needs to be small, to accomodate race condition in loop
  634.      */
  635.     timeout.tv_sec = (long) 1;
  636.     timeout.tv_usec = (long) 0;
  637.  
  638.     /*
  639.      * assume WAKE_QUEUEEMPTY is set
  640.      */
  641.     while ( DMA_ISFULL(DMAheader)) {
  642.         selmask = 1 << fd_qdss;
  643.         select( fd_qdss + 1, 0, &selmask, 0, &timeout);
  644.     }
  645.  
  646.     DMArequest = DMA_PUTBEGIN (DMAheader);
  647.     DMArequest->DMAtype = DISPLIST;
  648.     DMArequest->DMAdone &= ~REQUEST_DONE;    /* A NOOP !!  XXX dwm */
  649.     DMArequest->DMAdone = condition ;
  650.  
  651.     /*
  652.      * reinit DMAbuf and the pointer into it
  653.      */
  654.     
  655.     dma_word = DMAbuf = (u_short *) DMArequest->bufp;
  656.     req_buf_max = DMAbuf + req_buf_size;
  657. }
  658.  
  659. Get_fifo (condition)
  660. short condition; /* to be put in new packet header's DMAdone field */
  661. {
  662.     register VOLATILE struct fcc *sgfcc;
  663.     u_short cur_section;
  664.     u_short    next_section;
  665.     struct timeval timeout;
  666.     int selmask;
  667.  
  668.     sgfcc = fcc_cbcsr;
  669.  
  670.     /*
  671.      * Check for FIFO wrapping
  672.      */
  673.  
  674.     cur_section = *sg_next_fifo >> 14;    /* current section of FIFO */
  675.     next_section = (*sg_next_fifo + req_buf_size) >> 14; /* next section */
  676.     if ((cur_section != next_section) || (*sg_next_fifo > 0x7FFF)) {
  677.     while ((sgfcc->fwused) || (*change_section == 1)) ; /* ?? */
  678.         if (next_section == 2)
  679.             *sg_next_fifo = 0;
  680.         else
  681.             *sg_next_fifo = next_section * 0x4000;
  682.  
  683.     /*
  684.      * Modify CBCSR register when going into a new section.
  685.      */
  686.  
  687.         sgfcc->cbcsr = (sgfcc->cbcsr + 1) & 0xFFFD;
  688.         *change_section = 1;
  689.         sgfcc->thresh = 0x0000;
  690.         *(unsigned long *)&sgfcc->cbcsr =
  691.              (unsigned long)((ENTHRSH << 16) | sgfcc->cbcsr);
  692.     }
  693.     /*
  694.      * reinit DMAbuf and the pointer into it
  695.      */
  696.     
  697.     sg_fifo_type = DISPLIST;
  698.  
  699.  
  700.     dma_word = DMAbuf = (u_short *) SG_Fifo + (*sg_next_fifo & 0x3FFF);
  701.     req_buf_max = DMAbuf + req_buf_size;
  702. }
  703.